#include "../server.hpp"
#include <fstream>
#include <sys/stat.h>
#include <regex>

#define DEFAULT_TIMEOUT 30

//为了提高效率，把映射关系定义成全局
std::unordered_map<int, std::string> _statu_msg = {
    {100, "Continue"},
    {101, "Switching Protocol"},
    {102, "Processing"},
    {103, "Early Hints"},
    {200, "OK"},
    {201, "Created"},
    {202, "Accepted"},
    {203, "Non-Authoritative Information"},
    {204, "No Content"},
    {205, "Reset Content"},
    {206, "Partial Content"},
    {207, "Multi-Status"},
    {208, "Already Reported"},
    {226, "IM Used"},
    {300, "Multiple Choice"},
    {301, "Moved Permanently"},
    {302, "Found"},
    {303, "See Other"},
    {304, "Not Modified"},
    {305, "Use Proxy"},
    {306, "unused"},
    {307, "Temporary Redirect"},
    {308, "Permanent Redirect"},
    {400, "Bad Request"},
    {401, "Unauthorized"},
    {402, "Payment Required"},
    {403, "Forbidden"},
    {404, "Not Found"},
    {405, "Method Not Allowed"},
    {406, "Not Acceptable"},
    {407, "Proxy Authentication Required"},
    {408, "Request Timeout"},
    {409, "Conflict"},
    {410, "Gone"},
    {411, "Length Required"},
    {412, "Precondition Failed"},
    {413, "Payload Too Large"},
    {414, "URI Too Long"},
    {415, "Unsupported Media Type"},
    {416, "Range Not Satisfiable"},
    {417, "Expectation Failed"},
    {418, "I'm a teapot"},
    {421, "Misdirected Request"},
    {422, "Unprocessable Entity"},
    {423, "Locked"},
    {424, "Failed Dependency"},
    {425, "Too Early"},
    {426, "Upgrade Required"},
    {428, "Precondition Required"},
    {429, "Too Many Requests"},
    {431, "Request Header Fields Too Large"},
    {451, "Unavailable For Legal Reasons"},
    {501, "Not Implemented"},
    {502, "Bad Gateway"},
    {503, "Service Unavailable"},
    {504, "Gateway Timeout"},
    {505, "HTTP Version Not Supported"},
    {506, "Variant Also Negotiates"},
    {507, "Insufficient Storage"},
    {508, "Loop Detected"},
    {510, "Not Extended"},
    {511, "Network Authentication Required"}
};
std::unordered_map<std::string, std::string> mim_msg = {
    {".aac", "audio/aac"},
    {".abw", "application/x-abiword"},
    {".arc", "application/x-freearc"},
    {".avi", "video/x-msvideo"},
    {".azw", "application/vnd.amazon.ebook"},
    {".bin", "application/octet-stream"},
    {".bmp", "image/bmp"},
    {".bz", "application/x-bzip"},
    {".bz2", "application/x-bzip2"},
    {".csh", "application/x-csh"},
    {".css", "text/css"},
    {".csv", "text/csv"},
    {".doc", "application/msword"},
    {".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
    {".eot", "application/vnd.ms-fontobject"},
    {".epub", "application/epub+zip"},
    {".gif", "image/gif"},
    {".htm", "text/html"},
    {".html", "text/html"},
    {".ico", "image/vnd.microsoft.icon"},
    {".ics", "text/calendar"},
    {".jar", "application/java-archive"},
    {".jpeg", "image/jpeg"},
    {".jpg", "image/jpeg"},
    {".js", "text/javascript"},
    {".json", "application/json"},
    {".jsonld", "application/ld+json"},
    {".mid", "audio/midi"},
    {".midi", "audio/x-midi"},
    {".mjs", "text/javascript"},
    {".mp3", "audio/mpeg"},
    {".mpeg", "video/mpeg"},
    {".mpkg", "application/vnd.apple.installer+xml"},
    {".odp", "application/vnd.oasis.opendocument.presentation"},
    {".ods", "application/vnd.oasis.opendocument.spreadsheet"},
    {".odt", "application/vnd.oasis.opendocument.text"},
    {".oga", "audio/ogg"},
    {".ogv", "video/ogg"},
    {".ogx", "application/ogg"},
    {".otf", "font/otf"},
    {".png", "image/png"},
    {".pdf", "application/pdf"},
    {".ppt", "application/vnd.ms-powerpoint"},
    {".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
    {".rar", "application/x-rar-compressed"},
    {".rtf", "application/rtf"},
    {".sh", "application/x-sh"},
    {".svg", "image/svg+xml"},
    {".swf", "application/x-shockwave-flash"},
    {".tar", "application/x-tar"},
    {".tif", "image/tiff"},
    {".tiff", "image/tiff"},
    {".ttf", "font/ttf"},
    {".txt", "text/plain"},
    {".vsd", "application/vnd.visio"},
    {".wav", "audio/wav"},
    {".weba", "audio/webm"},
    {".webm", "video/webm"},
    {".webp", "image/webp"},
    {".woff", "font/woff"},
    {".woff2", "font/woff2"},
    {".xhtml", "application/xhtml+xml"},
    {".xls", "application/vnd.ms-excel"},
    {".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
    {".xml", "application/xml"},
    {".xul", "application/vnd.mozilla.xul+xml"},
    {".zip", "application/zip"},
    {".3gp", "video/3gpp"},
    {".3g2", "video/3gpp2"},
    {".7z", "application/x-7z-compressed"}
};


class Util
{
public:
    //分割字符串
    static size_t Spilt(const std::string& src,const std::string& sep,std::vector<std::string>* arr)
    {
        //"abc,sdf,ijk"  ","
        int offset = 0; //偏移量
        while(offset < src.size())
        {
            int pos = src.find(sep,offset);
            if(pos == std::string::npos)
            {
                //没找到，说明后面的offset后面的字符都是结果
                arr->push_back(src.substr(offset,pos-offset));
                return arr->size();
            }
            //这里可能有多个重复sep
            if(offset == pos){
                offset = pos + sep.size();
                continue;
            }
            //收集结果
            arr->push_back(src.substr(offset,pos-offset));
            offset = pos + sep.size();
        }
        return arr->size();
    }
    //读取文件内容
    static bool ReadFile(const std::string& filename,std::string* buf)
    {
        std::ifstream ifs(filename,std::ios::binary);
        if(!ifs.is_open())
        {
            DLOG("OPEN %s FAILED!",filename);
            return false;
        }
        int fsize = 0;
        //先把文件指针偏移到末尾，获取到文件的大小
        ifs.seekg(0,ifs.end);
        fsize = ifs.tellg();
        //回到起始，开始读取文件
        ifs.seekg(0,ifs.beg);
        buf->resize(fsize);
        //读取文件
        ifs.read(&(*buf)[0],fsize);
        if(!ifs.good())
        {
            DLOG("READ FILE %s FAILED!",filename);
            ifs.close();
            return false;
        }
        //记得关闭文件，防止资源泄露
        ifs.close();
        return true;
    }
    //写入文件
    static bool WriteFile(const std::string& filename,const std::string& buf)
    {
        std::ofstream ofs(filename,std::ios::binary | std::ios::trunc);
        if(!ofs.is_open())
        {
            DLOG("OPEN %s FAILED!",filename.c_str());
            return false;
        }
        //向文件写入
        ofs.write(buf.c_str(),buf.size());
        if(!ofs.good())
        {
            DLOG("WRITEFILE %s FAILED!",filename.c_str());
            ofs.close();
            return false;
        }
        ofs.close();
        return true;
    }
    //url编码
    static std::string UrlEnCode(const std::string& url,bool convert_space_to_plus)
    {
        //". - _ ~"以及数字字母字符采用绝对不编码，convert_space_to_plus -> 是否启用空格转+
        std::string ret;
        for(auto ch: url)
        {
            if(ch == '.' || ch == '-' || ch == '_' || ch == '~' || isalnum(ch))
            {
                ret += ch;
                continue;
            }
            //空格转+
            if(convert_space_to_plus && ch == ' ')
            {
                ret += '+';
                continue;
            }
            //其余都是需要转换的字符
            char tmp[4] = {0};
            snprintf(tmp,4,"%%%02X",ch);
            ret += tmp;
        }
        return ret;
    }
    static char HexToI(char ch)
    {
        if(ch >= '0' && ch <= '9')
        {
            return ch - '0';
        }
        else if(ch >= 'a' && ch <= 'z')
        {
            return ch - 'a' + 10;
        }
        else if(ch >= 'A' && ch <= 'Z')
        {
            return ch - 'A' + 10;
        }
        return -1; //错误
    }
    //url解码
    static std::string UrlDeCode(const std::string& url,bool convert_plus_to_space)
    {
        std::string ret;
        for(int i = 0;i<url.size();++i)
        {
            //判断convert_plus_to_space条件是否满足
            if(convert_plus_to_space && url[i] == '+')
            {
                ret += ' ';
                continue;
            }
            //遇到%后面的数，就把第一个数转换成16进制第二个数相加
            if(url[i] == '%')
            {
                char v1 = HexToI(url[i+1]);
                char v2 = HexToI(url[i+2]);
                char res = (v1 << 4) + v2;   
                ret +=  res;
                i += 2;
                continue;
            }
            //其他情况直接放入结果集即可
            ret += url[i];
        }
        return ret;
    }
    //通过响应状态码获得响应信息
    static std::string StatuDesc(int statu)
    {
        auto it = _statu_msg.find(statu);
        if (it != _statu_msg.end()) {
            return it->second;
        }
        return "Unknow";
    }
    static std::string GetMime(const std::string& filename)
    {
        //a.txt 找到文件后缀
        size_t pos = filename.find_last_of('.');
        if(pos == std::string::npos)
        {
            //没找到就是二进制流数据
            return "application/octet-stream";
        }
        std::string tmp = filename.substr(pos);
        auto it = mim_msg.find(tmp);
        if(it == mim_msg.end())
        {
            return "application/octet-stream";
        }
        return it->second;
    }
    //判断一个文件是否是目录
    static bool IsDir(const std::string& filename)
    {
        struct stat st;
        int ret = stat(filename.c_str(),&st);
        if(ret < 0)
        {
            return false;
        }
        return S_ISDIR(st.st_mode);
    }
    //判断一个文件是否是普通文件
    static bool IsRegular(const std::string& filename)
    {
        struct stat st;
        int ret = stat(filename.c_str(),&st);
        if(ret < 0)
        {
            return false;
        }
        return S_ISREG(st.st_mode);
    }
    //资源路径的有效性判断
    static bool IsValPath(const std::string& path)
    {
        //根据层数来判断当前路径是否在web根目录下
        //"/index.html"  "/../index.html"
        std::vector<std::string> vs;
        Spilt(path,"/",&vs);
        int level = 0;
        for(auto& str:vs)
        {
            if(str == "..")
            {
                --level;
                if(level < 0) return false; //任意一层小于0都是有问题的
                continue;
            }
            ++level;
        }
        return true;
    }
};


class HttpRequest
{
public:
    std::string _method; //请求方法
    std::string _path;   //资源路径
    std::string _version;//协议版本
    std::string _body;   //请求正文
    std::smatch _matches; //正则提取查询字符串
    std::unordered_map<std::string,std::string> _headers;  //头部字段
    std::unordered_map<std::string,std::string> _parame;  //查询字符串
public:
    HttpRequest():_version("HTTP/1.1"){}
    void ReSet()
    {
        _method.clear();
        _path.clear();
        _version.clear();
        _body.clear();
        std::smatch tmp; //用于交换清除
        _matches.swap(tmp);
        _headers.clear();
        _parame.clear();
    }
    //插入头部字段
    void SetHeader(const std::string& key,const std::string& val)
    {
        _headers.insert(std::make_pair(key,val));
    }
    //获取指定头部的值
    std::string GetHeader(const std::string& key)
    {
        auto it = _headers.find(key);
        if(it != _headers.end())
        {
            return it->second;
        }
        return "";
    }
    //查询指定头部的值是否存在
    bool HasHeader(const std::string& key)
    {
        auto it = _headers.find(key);
        if(it != _headers.end())
        {
            return true;
        }
        return false;
    }
    //插入查询字符串
    void SetParam(const std::string& key,const std::string& val)
    {
        _parame.insert(std::make_pair(key,val));
    }
    //获取指定查询字符串
    std::string GetParam(const std::string& key)
    {
        auto it = _parame.find(key);
        if(it != _parame.end())
        {
            return it->second;
        }
        return "";
    }
    //判断是否存在某个查询字符串
    bool HasParam(const std::string& key)
    {
        auto it = _parame.find(key);
        if(it != _parame.end())
        {
            return true;
        }
        return false;
    }
    //获取正文长度
    size_t Content_Length()
    {
        auto it = _headers.find("Content-Length");
        if(it == _headers.end())
        {
            return 0;
        }
        return std::stol(it->second);
    }
    //判断是否为短连接
    bool Close()
    {
        if(HasHeader("Connection") && GetHeader("Connection") == "keep-alive")
        {
            return false;
        }
        return true;
    }
};


class HttpResponse
{
public: 
    int _statu;             //响应状态
    bool _redirect_flag;    //是否重定向
    std::string _body;      //响应正文
    std::string _redirect_url;  //重定向url
    std::unordered_map<std::string,std::string> _headers;  //头部字段
public:
    HttpResponse():_statu(200),_redirect_flag(false){}
    HttpResponse(int statu):_statu(statu),_redirect_flag(false){}
    void ReSet()
    {
        _statu = 200;
        _redirect_flag = false;
        _body.clear();
        _redirect_url.clear();
        _headers.clear();
    }
    //插入头部字段
    void SetHeader(const std::string& key,const std::string& val)
    {
        _headers.insert(std::make_pair(key,val));
    }
    //获取指定头部的值
    std::string GetHeader(const std::string& key)
    {
        auto it = _headers.find(key);
        if(it != _headers.end())
        {
            return it->second;
        }
        return "";
    }
    //查询指定头部的值是否存在
    bool HasHeader(const std::string& key)
    {
        auto it = _headers.find(key);
        if(it != _headers.end())
        {
            return true;
        }
        return false;
    }
    //设置响应正文
    void SetContent(const std::string& body,const std::string& type)
    {
        _body = body;
        SetHeader("Content-Length",type);
    }
    //设置重定向
    void SetRedirect(const std::string& url,int statu = 302)
    {
        _statu = statu;
        _redirect_flag = true;
        _redirect_url = url;
    }
     //判断是否为短连接
    bool Close()
    {
        if(HasHeader("Connection") && GetHeader("Connection") == "keep-alive")
        {
            return false;
        }
        return true;
    }
};



typedef enum {
    RECV_HTTP_ERROR,
    RECV_HTTP_LINE,
    RECV_HTTP_HEAD,
    RECV_HTTP_BODY,
    RECV_HTTP_OVER,
}HttpRecvStatu;

#define MAX_LINE 8192

class HttpContent
{
private:
    int _resp_statu;     //响应状态码
    HttpRecvStatu _recv_statu;   //当前解析阶段
    HttpRequest _request;  //已经解析得到的信息
private:
    bool ParseLine(const std::string& line)
    {
        std::smatch matches;
        std::regex e("(GET|POST|HEAD|DELETE|PUT) ([^?]*)(?:\\?(.*))? (HTTP/1\\.[01])(?:\r|\r\n)?",std::regex::icase); //匹配请求方法的正则表达式
        bool ret = regex_match(line,matches,e);
        if(ret == false) return false;
        //结果如下：
        //0 : GET /hello/login?user=xiaoming&passwd=123456 HTTP/1.1
        //1 : GET
        //2 : /hello/login
        //3 : user=xiaoming&passwd=123456
        //4 : HTTP/1.1
        _request._method = matches[1];
        //这里统一转换为大写，兼容性更强
        std::transform(_request._method.begin(),_request._method.end(),_request._method.begin(),::toupper);
        //这里资源路径需要解码且不需要+转空格
        _request._path = Util::UrlDeCode(matches[2],false);
        _request._version = matches[4];
        //这个查询字符串要特殊处理一下
        std::string param = matches[3];
        std::vector<std::string> vs;
        Util::Spilt(param,"&",&vs);
        //通过等号进行继续分割，得到key val
        for(auto& str:vs)
        {
            size_t pos = str.find('=');
            if(pos == std::string::npos)
            {
                //没找到，认为是有问题的，返回错误
                _resp_statu = 400;  //BAD REQUEST
                _recv_statu = RECV_HTTP_ERROR;
                return false;
            }
            //这里得到的key和val也是需要进行解码的且需要空格转+
            std::string key = Util::UrlDeCode(str.substr(0,pos),true);
            std::string val = Util::UrlDeCode(str.substr(pos+1),true);
            _request.SetParam(key,val);
        }
        return true;
    }
    bool RecvLine(Buffer* buf)
    {
        if(_recv_statu != RECV_HTTP_LINE) return false;
        //接收一行
        std::string line = buf->GetLineAndPop();
        if(line.size() == 0)
        {
            //没有一行，有可能是一行的数据太大了，也可能是不够一行的数据
            if(buf->ReadAbleSize() > MAX_LINE)
            {
                //{414, "URI Too Long"}
                _resp_statu = 414;
                _recv_statu = RECV_HTTP_ERROR;
                return false;
            }
            return true;
        }
        if(line.size() > MAX_LINE)
        {
            _resp_statu = 414;
            _recv_statu = RECV_HTTP_ERROR;
            return false;
        }
        bool ret = ParseLine(line);
        if(ret == false)
        {
            return false;
        }
        //首行处理完毕，进入头部阶段
        _recv_statu = RECV_HTTP_HEAD;
        return true;
    }
    bool RecvHead(Buffer* buf)
    {
        if(_recv_statu != RECV_HTTP_HEAD) return false;
        //这里是有多行数据，而且数据都是以key： val的形式
        while(true)
        {
            std::string line = buf->GetLineAndPop();
            if(line.size() == 0)
            {
                //没有一行，有可能是一行的数据太大了，也可能是不够一行的数据
                if(buf->ReadAbleSize() > MAX_LINE)
                {
                    //{414, "URI Too Long"}
                    _resp_statu = 414;
                    _recv_statu = RECV_HTTP_ERROR;
                    return false;
                }
                return true;
            }
            if(line.size() > MAX_LINE)
            {
                _resp_statu = 414;
                _recv_statu = RECV_HTTP_ERROR;
                return false;
            }
            if(line == "\n" || line == "\r\n") break; //这里说明头部已经解析完成
            bool ret = ParseHead(line);
            if(ret == false) return false;
        }
        //头部解析完成，进行正文解析
        _recv_statu = RECV_HTTP_BODY;
        return true;
    }
    bool ParseHead(std::string& line)
    {
        //去掉换行符
        if(line.back() == '\n') line.pop_back();
        if(line.back() == '\r') line.pop_back();
        //这里都是key： val的形式
        size_t pos = line.find(": ");
        if(pos == std::string::npos)
        {
            //解析失败
            _resp_statu = 400;
            _recv_statu = RECV_HTTP_ERROR;
            return false;
        }
        std::string key = line.substr(0,pos);
        std::string val = line.substr(pos+2);
        _request.SetHeader(key,val);
        return true;
    }
    bool RecvBody(Buffer* buf)
    {
        if(_recv_statu != RECV_HTTP_BODY) return false;
        //正文数据大小为0，则直接返回即可
        size_t content_len = _request.Content_Length();
        if(content_len == 0){
            //解析完毕，直接返回
            _recv_statu = RECV_HTTP_OVER;
            return true;
        }
        //获得剩下应该获取的正文长度
        size_t real_len = content_len - _request._body.size();
        //缓冲区的数据大于剩余正文长度，取出当前所需
        if(buf->ReadAbleSize() >= real_len)
        {
            _request._body.append(buf->ReadPosition(),real_len);
            //这里不要忘了向后移动
            buf->MoveReadOffSet(real_len);
            _recv_statu = RECV_HTTP_OVER;
            return true;
        }
        //这里的缓冲区数据不够，则把数据放到正文中，然后返回即可
        _request._body.append(buf->ReadPosition(),buf->ReadAbleSize());
        //这里不要忘了向后移动
        buf->MoveReadOffSet(buf->ReadAbleSize());
        return true;
    }
public:
    HttpContent():_resp_statu(200),_recv_statu(RECV_HTTP_LINE){};
    void Reset()
    {
        _resp_statu = 200;
        _recv_statu = RECV_HTTP_LINE;
        _request.ReSet();
    }
    int Statu() { return _resp_statu; }
    HttpRecvStatu RecvStatu() { return _recv_statu; }
    HttpRequest& RecvReq() { return _request; }
    //接收并解析请求
    void HttpRecvReqest(Buffer* buffer)
    {
        //根据不同的状态进入不同的函数，这里一个函数处理完成之后会立刻进入下一个函数，完成全过程
        switch(_recv_statu){
            case RECV_HTTP_LINE: RecvLine(buffer);
            case RECV_HTTP_HEAD: RecvHead(buffer);
            case RECV_HTTP_BODY: RecvBody(buffer);
        }
    }
};


class HttpServer
{
private:
    using Functor = std::function<void(const HttpRequest&,HttpResponse*)>;
    using Handler = std::vector<std::pair<std::regex,Functor>>;
    //各种方法的路由表，第一个是正则表达式，第二个是方法
    Handler _get_route;
    Handler _post_route;
    Handler _put_route;
    Handler _delete_route;
    std::string _base_dir; //静态资源根目录
    TcpServer _server;
private:
    void ErrorHandler(const HttpRequest& req,HttpResponse* resp)
    {
        //1.组织一个错误的页面
        std::string body;
        body += "<html>";
        body += "<head>";
        body += "<meta charset='utf-8'>";
        body += "</head>";
        body += "<body>";
        body += "<h1>";
        body += std::to_string(resp->_statu);
        body += " ";
        body += Util::StatuDesc(resp->_statu);
        body += "</h1>";
        body += "</body>";
        body += "</html>";
        //2.讲页面数据放入到resp中
        resp->SetContent(body,"text/html");
    }
    //根据http来组织httpResponse各要素
    void WriteResponse(const PtrConnection& conn,HttpRequest& req,HttpResponse& resp)
    {
        //1.完善头部字段
        if(req.Close() == true)
        {
            resp.SetHeader("Connection","Close");
        }
        else{
            resp.SetHeader("Connection","keep-alive");
        }
        if(!resp._body.empty() && !resp.HasHeader("Content-Length"))
        {
            resp.SetHeader("Content-Length",std::to_string(resp._body.size()));
        }
        if(!resp._body.empty() && !resp.HasHeader("Content-Type"))
        {
            resp.SetHeader("Content-Type","application/octet-stream");
        }
        //是否设置重定向
        if(resp._redirect_flag)
        {
            resp.SetHeader("Location",resp._redirect_url);
        }
        //2.填充resp信息 协议版本，响应状态码，响应状态码描述
        std::stringstream str;
        str << req._version <<" "<< std::to_string(resp._statu) << " " << Util::StatuDesc(resp._statu) << "\r\n";
        //响应头部
        for(auto& head : resp._headers)
        {
            str << head.first <<": " << head.second << "\r\n";
        }
        str << "\r\n";
        str << resp._body;
        //3.发送数据
        conn->Send(str.str().c_str(),str.str().size());
    }
    //静态资源处理
    bool IsFilerHandler(const HttpRequest& req)
    {
        //1.必须设置静态资源根目录
        if(req._path.empty())
        {
            return false;
        }
        //2.必须是GET或者是HEAD方法
        if(req._method != "GET" && req._method != "HEAD"){
            return false;
        }
        //3.必须是合法的资源路径
        if(!Util::IsValPath(req._path))
        {
            return false;
        }
        //4.资源必须存在
        //先添加上静态资源根目录，防止后面出错用另外一个变量来接收
        std::string req_path = _base_dir + req._path;
        // "/" 最后一个字符是/，那么添加上"index.html"
        if(req_path.back() == '/'){
            req_path += "index.html";
        }
        //判断是否是一个文件
        if(!Util::IsRegular(req_path)){
            return false;
        }
        return true;
    }
    bool FilerHandler(HttpRequest& req,HttpResponse* resp)
    {
        //先确定路径
        std::string req_path = _base_dir + req._path;
        if(req_path.back() == '/'){
            req_path += "index.html";
        }
        //把要获取的资源读取出来放到resp中的body中，并设置mime
        bool ret = Util::ReadFile(req_path,&(resp->_body));
        if(ret == false){
            return false;
        }
        //设置mime
        resp->SetHeader("Content-Type",Util::GetMime(req_path));
        return true;
    }
    //功能性资源处理
    void Dispatcher(HttpRequest& req,HttpResponse* resp,Handler& handlers)
    {
        //通过查看不同的方法的路由表，如果找到方法就执行对应的方法，如果没有找到就返回404
        for(auto& handler:handlers)
        {
            const std::regex& re = handler.first;
            const Functor& func = handler.second;
            bool ret = std::regex_match(req._path,req._matches,re);
            if(ret == false)
            {
                continue; //没有找到，继续查找
            }
            //找到就执行对应的函数
            return func(req,resp);
        }
        //返回404
        resp->_statu = 404;
    }  
    void Route(HttpRequest& req,HttpResponse* resp)
    {
        //分成两种 -> 如果是静态资源请求则调用静态资源请求处理
        //如果是功能性资源请求则调用对应的函数处理
        if(IsFilerHandler(req))
        {
            FilerHandler(req,resp);
        }
        //功能性请求
        if(req._method == "GET" || req._method == "HEAD"){
            return Dispatcher(req,resp,_get_route);
        }
        else if(req._method == "POST"){
            return Dispatcher(req,resp,_post_route);
        }else if(req._method == "PUT"){
            return Dispatcher(req,resp,_put_route);
        }
        else if(req._method == "DELETE"){
            return Dispatcher(req,resp,_delete_route);
        }
        //不是上述方法，则返回405
        resp->_statu = 405; //Method Not Allowed
    }
    //设置上下文
    void Onconnect(const PtrConnection& conn)
    {
        conn->SetContext(HttpContent());
        DLOG("New Connection %p",conn.get());
    }
    //解析+处理
    void OnMessage(const PtrConnection& conn,Buffer* buf)
    {
        while(buf->ReadAbleSize() > 0)
        {
            //1.获取上下文
            HttpContent* content = conn->Context()->get<HttpContent>();
            //2.通过解析上下文得到httprequest
            content->HttpRecvReqest(buf);
            HttpRequest& req = content->RecvReq();
            HttpResponse resp(content->Statu());
            //这里数据解析可能出错
            if(content->Statu() >= 400)
            {
                //进行错误响应，关闭连接
                ErrorHandler(req,&resp);  //填充一个错误的页面返回
                WriteResponse(conn,req,resp);  //组织+响应
                //关闭连接之前应该重置一下上下文，防止状态一直处理错误的状态
                content->Reset();
                //这里出错了，为了提高服务器的效率，直接把缓冲区中的数据清空
                buf->MoveReadOffSet(buf->ReadAbleSize());
                conn->ShutDown();  //关闭连接
                return;
            }
            //这里有可能解析还没有完成，重新开始
            if(content->RecvStatu() != RECV_HTTP_OVER){
                return;
            }
            //3.请求路由
            Route(req,&resp);
            //4.组织httpresponse并发送
            WriteResponse(conn,req,resp);
            //5.重置上下文
            content->Reset();
            //6.是否是短连接，关闭
            if(resp.Close()) conn->ShutDown();
        }
    }
public:
    HttpServer(int port,int timeout = DEFAULT_TIMEOUT):_server(port)
    {
        _server.SetActiveRelease(timeout);
        _server.SetConnectCallback(std::bind(&HttpServer::Onconnect,this,std::placeholders::_1));
        _server.SetMessageCallback(std::bind(&HttpServer::OnMessage,this,std::placeholders::_1,std::placeholders::_2));
    }
    void SetBaseDir(const std::string& path){
        assert(Util::IsDir(path) == true);
        _base_dir = path;
    }
    //建立正则表达式和对应处理函数的映射关系
    void Get(const std::string& pattern,const Functor& func){
        _get_route.push_back(std::make_pair(std::regex(pattern),func));
    }
    void Post(const std::string& pattern,const Functor& func){
        _post_route.push_back(std::make_pair(std::regex(pattern),func));
    }
    void Put(const std::string& pattern,const Functor& func){
        _put_route.push_back(std::make_pair(std::regex(pattern),func));
    }
    void Delete(const std::string& pattern,const Functor& func){
        _delete_route.push_back(std::make_pair(std::regex(pattern),func));
    }
    void SetThreadCount(int count)
    {
        _server.SetThreadCount(count);
    }
    void Listen(){
        _server.Start();
    }
};